#include "vcl_stl.h"

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#ifdef BK_AIX
   static string SysName = "aix";
#endif
#ifdef BK_LINUX
   static string SysName = "linux";
#endif
#ifdef BK_HP
   static string SysName = "hp";
#endif
#ifdef BK_SOLARIS
   static string SysName = "solaris";
#endif

static string DllSuffix;

static int ReadLine(FILE *f, char *s, int MaxLen);
static string EnvEvaluate(const string &Str);
static void RightTrim(char *s);
static int System(const char *s, bool Check = false);

static int System(const char *s, bool Check)
{
   printf("executing : %s\n", s);
   int r = system(s);

   if ( Check )
   {
      if ( r == -1 || !WIFEXITED(r) || WEXITSTATUS(r) != 0 )
      {
         printf("Command failed.\n");
         exit(8);
      }
   }

   return r;
}

bool FileExist(const char *FileName)
{
   struct stat Stat;

   return stat(FileName, &Stat) != -1;
}

int StrRCmp(const char *s1, const char *s2)
{
   if( strlen(s1) < strlen(s2) )
      return 1;

   return strcmp(s1 + strlen(s1) - strlen(s2), s2);
}

static void RightTrim(char *s)
{
   int i;

   for ( i = strlen(s) - 1; i >= 0 && s[i] == ' '; i--)
   {
      s[i] = '\0';
   }
}

static int ReadLine(FILE *f, char *s, int MaxLen)
{
   int i;
   int c;

   for ( i = 0; i < MaxLen; )
   {
      c = fgetc(f);
      if ( c == '\t' || c == '\0' )
      {
         c = ' ';
      }
      if ( c == EOF || c == '\n' )
      {
         break;
      }
      s[i++] = c;
   }

   s[i] = '\0';

   if ( i == MaxLen )
   {
      for ( ; ; )
      {
         c = fgetc(f);
         if ( c == EOF || c == '\n' )
         {
            break;
         }
      }
   }

   if ( c == EOF && i == 0 )
   {
      return -1;
   }
   else
   {
      return i;
   }
}

static string EnvEvaluate(const string &Str)
{
   int i, j;
   char *Env;
   string Result;

   for ( i = 0; ; )
   {
      j = Str.find('$', i);
      if ( j == string::npos )
      {
         Result += Str.substr(i);
         break;
      }
      Result += Str.substr(i, j - i);
      i = j + 1;
      if ( Str[i] == '{' )
      {
         i++;
         j = Str.find('}', i);
         if ( j == string::npos )
         {
            break;
         }
         Env = getenv(Str.substr(i, j - i).c_str());
         j++;
      }
      else
      {
         for ( j = i; ; j++ )
         {
            if ( Str[j] != '_' && !isalnum(Str[j]) )
            {
               break;
            }
         }
         Env = getenv(Str.substr(i, j - i).c_str());
      }
      if ( Env != NULL )
      {
         Result += Env;
      }
      i = j;
   }

   return Result;
}

static const char *Welcome[] = 
{
   "",
   "",
   "          Simjie's",
   "            _____ _____ __  __            ____       _______ ",
   "           / ____|_   _|  \\/  |          |  _ \\   /\\|__   __|",
   "          | (___   | | | \\  / |  ______  | |_) | /  \\  | |   ",
   "           \\___ \\  | | | |\\/| | |______| |  _ < / /\\ \\ | |   ",
   "           ____) |_| |_| |  | |          | |_) / ____ \\| |   ",
   "          |_____/|_____|_|  |_|          |____/_/    \\_\\_|   ",
                                               

   "",
   "",
   "                          SIM-BAT installation",
   "",
   NULL
};

static string DesPath;
static string ProfilePath;
static bool Copyright = false;

static bool Init();
static bool Install();

static bool Init()
{
   int i;
   char Line[2048 + 1];

   for ( i = 0; Welcome[i] != NULL; i++ )
   {
      printf("%s\n", Welcome[i]);
   }

   printf("                Version %s  ( %s )\n\n\n", VERSION_STRING, EDITION_STRING);

   {
      FILE *f = fopen("install.cfg", "rt");
      if ( f != NULL )
      {
         for ( ; ; )
         {
            char Line[2048 + 1];
            if ( ReadLine(f, Line, 2048) == -1 )
            {
               break;
            }
            RightTrim(Line);
            if ( strcmp(Line, "copyright=true") == 0 )
            {
               Copyright = true;
               break;
            }
         }
         fclose(f);
      }
   }

   if ( Copyright )
   {
      printf("  Copyright(C) 2013, 2018, Shenzhen Simjie Information Technology Ltd.\n\n\n");
   }

   printf("Destination path[$HOME/simbat] : ");
   ReadLine(stdin, Line, 2048);
   RightTrim(Line);

   if ( Line[0] == '\0' )
   {
      DesPath = "$HOME/simbat";
   }
   else
   {
      DesPath = Line;
   }

   bool IsBash = false;

   {
      const char *s = getenv("SHELL");

      if ( s != NULL && StrRCmp(s, "/bash") == 0 )
      {
         IsBash = true;
      }
   }

   printf("Profile path[$HOME/%s] : ", IsBash ? ".bash_profile" : ".profile");
   ReadLine(stdin, Line, 2048);
   RightTrim(Line);
   ProfilePath = Line;

   if ( Line[0] == '\0' )
   {
      if ( IsBash )
      {
         ProfilePath = "$HOME/.bash_profile";
      }
      else
      {
         ProfilePath = "$HOME/.profile";
      }
   }
   else
   {
      ProfilePath = Line;
   }

   printf("\n");
   printf("Destination path = %s\n", DesPath.c_str());
   printf("Profile path     = %s\n", ProfilePath.c_str());
   printf("\n");
   printf("Is that ok?  y : continue installation; n : quit to shell\n");

   for ( ; ; )
   {
      printf("[y/n] : ");
      ReadLine(stdin, Line, 2048);
      if ( Line[0] == 'y' || Line[0] == 'Y' ||
           Line[0] == 'n' || Line[0] == 'N' )
      {
         break;
      }
   }

   return Line[0] == 'y' || Line[0] == 'Y';
}

static bool Install()
{
   int i;
   char Command[8192 + 1];
   string Archive;
   string EnvLibPath;

   if ( SysName == "aix" )
   {
      DllSuffix = "a";
      Archive = "simbat.tar.Z";
      EnvLibPath = "LIBPATH";
   }

   if ( SysName == "linux" )
   {
      DllSuffix = "so";
      Archive = "simbat.zip";
      EnvLibPath = "LD_LIBRARY_PATH";
   }

   if ( SysName == "hp" )
   {
      DllSuffix = "so";
      Archive = "simbat.zip";
      EnvLibPath = "LD_LIBRARY_PATH";
   }

   if ( SysName == "solaris" )
   {
      DllSuffix = "so";
      Archive = "simbat.zip";
      EnvLibPath = "LD_LIBRARY_PATH";
   }
 
   printf("\n");
   System("simbat_ctl stop 2>/dev/null");
   snprintf(Command, 8192, "mkdir %s 2>/dev/null", DesPath.c_str());
   System(Command);
   snprintf(Command, 8192, "cp %s %s", Archive.c_str(), DesPath.c_str());
   System(Command);
   snprintf(Command, 8192, "cp install.cfg %s", DesPath.c_str());
   System(Command);

   if ( chdir(EnvEvaluate(DesPath).c_str()) == -1 )
   {
      fprintf(stderr, "chdir(%s) fail, errno = %d\n",
         DesPath.c_str(), errno);
      return false;
   }

   if ( SysName == "aix" )
   {
      System("uncompress simbat.tar.Z", true);
      System("tar -xvf simbat.tar", true);
      System("rm simbat.tar");
   }
   else
   {
      System("unzip -o simbat.zip", true);
      System("rm simbat.zip");
   }

   snprintf(Command, 8192, "mv install.cfg etc");
   System(Command);

   if ( !FileExist("etc/config.xml") )
   {
      System("cp etc/config_default.xml etc/config.xml");
   }

   if ( !FileExist("etc/http_post.ini") )
   {
      System("cp etc/http_post_default.ini etc/http_post.ini");
   }

   FILE *f;
   vector<string> Text;

   printf("executing : edit %s\n", ProfilePath.c_str());
   f = fopen(EnvEvaluate(ProfilePath).c_str(), "rt");

   if ( f != NULL )
   {
      for ( ; ; )
      {
         char Line[2048 + 1];
         if ( ReadLine(f, Line, 2048) == -1 )
         {
            break;
         }
         Text.push_back(Line);
      }
      fclose(f);
   }

   f = fopen(EnvEvaluate(ProfilePath).c_str(), "wt");

   if ( f == NULL )
   {
      fprintf(stderr, "Can not edit %s\n", ProfilePath.c_str());
      return false;
   }

   for ( i = 0; i < Text.size() &&
                strcmp(Text[i].c_str(), "#=== SIM-BAT ===") != 0; i++ )
   {
      fprintf(f, "%s\n", Text[i].c_str());
   }

   fprintf(f, "#=== SIM-BAT ===\n");
   fprintf(f, "export SIMBAT_BASE=%s\n", DesPath.c_str());
   fprintf(f, "export %s=$%s:$SIMBAT_BASE/lib\n", EnvLibPath.c_str(),
      EnvLibPath.c_str());
   fprintf(f, "export PATH=$PATH:$SIMBAT_BASE/bin\n");
   fprintf(f, "#=== SIM-BAT ===\n");

   for ( i++; i < Text.size() &&
                strcmp(Text[i].c_str(), "#=== SIM-BAT ===") != 0; i++ )
      ;

   for ( i++; i < Text.size(); i++ )
   {
      fprintf(f, "%s\n", Text[i].c_str());
   }

   fclose(f);
   printf("\n");
   printf("Installation successful.\n");
   printf("File %s was changed, please re-login.\n", ProfilePath.c_str());
   printf("\n");
   printf("Thank you for chosing %sSIM-BAT.\n", Copyright ? "Simjie's " : "");
   printf("\n");
   return true;
}

int main(void)
{
   if ( !Init() )
   {
      return 8;
   }

   if ( !Install() )
   {
      return 8;
   }

   return 0;
}
